#ifndef GPT_H
#define GPT_H

#include <Arduino.h>
#include "HTTPClient.h"
#include <ArduinoJson.h>
#include <base64.h>
#include <WiFi.h>
#include "Tts.h"
#include "FreeRTOS.h"
#include "task.h"
#include <ESP32Servo.h>

Servo servo1; // 舵机连接到GPIO3
// 新增的标志变量和互斥锁
volatile bool updateDisplayFlag = false;
volatile bool updateTextFlag = false;
SemaphoreHandle_t xSemaphore = NULL;
String displayText;
SemaphoreHandle_t xSemaphore1 = NULL;

// 3. Replace with your MiniMax API key
String apiUrl = "https://api.minimax.chat/v1/text/chatcompletion_v2";
const char *apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiIyMzQ1dm9yIiwiVXNlck5hbWUiOiIyMzQ1dm9yIiwiQWNjb3VudCI6IiIsIlN1YmplY3RJRCI6IjE3NTk0ODIxODAxMDAxNzAyMDgiLCJQaG9uZSI6IjE1MDcyNjQxNTYxIiwiR3JvdXBJRCI6IjE3NTk0ODIxODAwOTU5NzU5MDQiLCJQYWdlTmFtZSI6IiIsIk1haWwiOiIiLCJDcmVhdGVUaW1lIjoiMjAyNC0xMC0xNCAyMjoyODo0NSIsImlzcyI6Im1pbmltYXgifQ.xcIqNlrjffSbx2JLnBmGvh7XHL0j941Vo3qYFo_zxWZD6yfVqCp4nU-AQP6zvXxZBK3G3ocjzUXgd0WpnUrYaUWwOVkpKUbhMBGgmmXxOg4N8vcWCkgN3LbQYkqD5_n7II0ubZjIe9SrWOds9T4m6NLgVZZhEMU0JpmL9w2S2JLu_Ce1yIom3zg7zo1_wopnIWoEdNwGLi9P_GqiwPnGo7WR3p6Qo1LJsYk9amyl4sZk2daYMP1BQG07IlDh4Po3cS7HbioAXMMH-I6iJ0evR227rEUi2A4_I8acgTsOTSj-5UMmUJ_aKTLMuS_t8qz_wzcu_m0mas_eWQVVb0-Ggg";
String token_key = String("Bearer ") + apiKey;
// 3. Replace with your baidu voice detect token
// 百度 API 鉴权配置
String baidu_apiid = "BXL2YS33B2AAIt5w67Xw5XDq";
String baidu_apisecret = "pb2zIW2Nch2uNtc9Wt4lhk9hDKPK4eKX";
// 豆包API鉴权
String doubao_url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";
String doubao_apiKey = "e2238fa2-df26-4567-b978-12133201c8ab";
// 2. Replace with your ali_apiKey API key
const char *ali_apiKey = "sk-76a347d34b8d4359b39c6415d82b1695";
String ali_url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
String ali_image_apiUrl = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
const int adc_data_len = 8000 * 3;
const int data_json_len = adc_data_len * 3;
uint16_t *adc_data;
char *data_json;
JsonDocument jsonDoc;
String baidu_token_key;

//----------------------百度TTS本地鉴权---------------------------------
String getAccessToken(String _Baidu_TTS_ID, String _Baidu_TTS_key)
{
    // 动态生成获取访问令牌的 URL
    String token_url = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + _Baidu_TTS_ID + "&client_secret=" + _Baidu_TTS_key;
    Serial.println("----------------百度TTS本地鉴权开始------------");
    // 创建 HTTP 客户端
    HTTPClient http;
    http.setTimeout(4000);
    http.begin(token_url);

    int httpResponseCode = http.POST("");
    String accessToken = "";

    if (httpResponseCode > 0)
    {
        String response = http.getString();
        // 解析 JSON 响应以获取访问令牌
        JsonDocument doc;
        deserializeJson(doc, response);
        accessToken = doc["access_token"].as<String>();
    }
    else
    {
        Serial.print("发送POST错误: ");
        Serial.println(httpResponseCode);
    }

    http.end();
    return accessToken;
}

//-----------------------------------------------获取GPT文本回答------------------------------------------------
// 获取MiniMAX GPT文本回答
String get_MiniMAX_Answer(String inputText)
{
    HTTPClient http;
    http.setTimeout(4000);
    http.begin(apiUrl);
    http.addHeader("Content-Type", "application/json");
    http.addHeader("Authorization", token_key);
    String payload = "{\"model\":\"abab5.5s-chat\",\"messages\":[{\"role\": \"system\",\"content\": \"你是鹏鹏的生活助手机器人，要求下面的回答严格控制在300字符以内。\"},{\"role\": \"user\",\"content\": \"" + inputText + "\"}]}";
    int httpResponseCode = http.POST(payload);
    if (httpResponseCode == 200)
    {
        String response = http.getString();
        http.end();
        Serial.println(response);
        // Parse JSON response
        deserializeJson(jsonDoc, response);
        String outputText = jsonDoc["choices"][0]["message"]["content"];
        // 设置标志变量和显示文本
        if (xSemaphore != NULL)
        {
            xSemaphoreTake(xSemaphore, portMAX_DELAY);
            displayText = String("A:" + outputText);
            updateDisplayFlag = true;
            xSemaphoreGive(xSemaphore);
        }
        return outputText;
        // Serial.println(outputText);
    }
    else
    {
        http.end();
        Serial.printf("Error %i \n", httpResponseCode);
        speech("语言大模型故障，请检查api是否失效");
        return "error";
    }
}
// 获取豆包文本回答
String get_Doubao_Answer(String inputText)
{
    HTTPClient http;
    String token_key = String("Bearer ") + doubao_apiKey;
    http.setTimeout(20000);
    http.begin(doubao_url);
    http.addHeader("Content-Type", "application/json");
    http.addHeader("Authorization", token_key);
    String payload = "{\"model\":\"ep-20240722231221-mn7ff\",\"messages\":[{\"role\":\"system\",\"content\":\"你是我的AI助手vor，你必须用中文回答且字数不超过200个\"},{\"role\":\"user\",\"content\":\"" + inputText + "\"}],\"temperature\": 0.3}";

    int httpResponseCode = http.POST(payload);
    if (httpResponseCode == 200)
    {
        String response = http.getString();
        http.end();
        Serial.println(response);

        // Parse JSON response
        deserializeJson(jsonDoc, response);
        String outputText = jsonDoc["choices"][0]["message"]["content"];
        // 设置标志变量和显示文本
        if (xSemaphore != NULL)
        {
            xSemaphoreTake(xSemaphore, portMAX_DELAY);
            displayText = String("A:" + outputText);
            updateDisplayFlag = true;
            xSemaphoreGive(xSemaphore);
        }
        return outputText;
    }
    else
    {
        http.end();
        Serial.printf("Error %i \n", httpResponseCode);
        return "error";
    }
}
// 获取文心一言文本回答
String get_Baidu_Answer(String inputText)
{
    HTTPClient http;
    String baidu_apiUrl = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + baidu_token_key;
    http.setTimeout(10000);
    http.begin(baidu_apiUrl);
    http.addHeader("Content-Type", "application/json");
    // http.addHeader("access_token", String(access_token));
    String payload = "{\"messages\":[{\"role\": \"user\",\"content\": \"" + inputText + "\"}]}";
    int httpResponseCode = http.POST(payload);
    if (httpResponseCode == 200)
    {
        String response = http.getString();
        http.end();
        Serial.println(response);

        // Parse JSON response
        deserializeJson(jsonDoc, response);
        String outputText = jsonDoc["result"];
        // 设置标志变量和显示文本
        if (xSemaphore != NULL)
        {
            xSemaphoreTake(xSemaphore, portMAX_DELAY);
            displayText = String("A:" + outputText);
            updateDisplayFlag = true;
            xSemaphoreGive(xSemaphore);
        }
        return outputText;
    }
    else
    {
        http.end();
        Serial.printf("Error %i \n", httpResponseCode);
        return "error";
    }
}
// 获取ali文本回答
String get_Ali_Answer(String inputText)
{
    HTTPClient http;
    http.setTimeout(10000);
    http.begin(ali_url);
    http.addHeader("Content-Type", "application/json");
    http.addHeader("Authorization", String(ali_apiKey));
    String payload = "{\"model\":\"qwen-turbo\",\"input\":{\"messages\":[{\"role\": \"system\",\"content\": \"你是鹏鹏的生活助手机器人，要求下面的回答严格控制在256字符以内。\"},{\"role\": \"user\",\"content\": \"" + inputText + "\"}]}}";
    int httpResponseCode = http.POST(payload);
    if (httpResponseCode == 200)
    {
        String response = http.getString();
        http.end();
        Serial.println(response);

        // Parse JSON response
        deserializeJson(jsonDoc, response);
        String outputText = jsonDoc["output"]["text"];
        // 设置标志变量和显示文本
        if (xSemaphore != NULL)
        {
            xSemaphoreTake(xSemaphore, portMAX_DELAY);
            displayText = String("A:" + outputText);
            updateDisplayFlag = true;
            xSemaphoreGive(xSemaphore);
        }
        return outputText;
        // Serial.println(outputText);
    }
    else
    {
        http.end();
        Serial.printf("Error %i \n", httpResponseCode);
        return "error";
    }
}

// stt语音识别
String sendToSTT()
{
    // 创建 HTTP 客户端
    HTTPClient http_client;
    http_client.setTimeout(4000);
    memset(data_json, '\0', data_json_len * sizeof(char));
    strcat(data_json, "{");
    strcat(data_json, "\"format\":\"pcm\",");
    strcat(data_json, "\"rate\":16000,");
    strcat(data_json, "\"dev_pid\":1537,");
    strcat(data_json, "\"channel\":1,");
    strcat(data_json, "\"cuid\":\"Sbu0ZJFdgQePo3lQkhs3IpQDm2iAEa7j\",");
    strcat(data_json, "\"token\":\"");
    strcat(data_json, baidu_token_key.c_str());
    strcat(data_json, "\",");
    sprintf(data_json + strlen(data_json), "\"len\":%d,", adc_data_len * 2);
    strcat(data_json, "\"speech\":\"");
    strcat(data_json, base64::encode((uint8_t *)adc_data, adc_data_len * sizeof(uint16_t)).c_str());
    strcat(data_json, "\"");
    strcat(data_json, "}");
    // Serial.println(data_json);
    static int httpCode;
    http_client.begin("http://vop.baidu.com/server_api"); // https://vop.baidu.com/pro_api
    http_client.addHeader("Content-Type", "application/json");
    httpCode = http_client.POST(data_json);

    if (httpCode == 200)
    {
        if (httpCode == HTTP_CODE_OK)
        {
            String response = http_client.getString();
            http_client.end();
            Serial.print(response);
            deserializeJson(jsonDoc, response);
            String question = jsonDoc["result"][0];
            // 输出结果
            Serial.println("Input:" + question);
            // 设置标志变量和显示文本
            if (xSemaphore != NULL)
            {
                xSemaphoreTake(xSemaphore, portMAX_DELAY);
                displayText = String("Q:" + question);
                updateDisplayFlag = true;
                xSemaphoreGive(xSemaphore);
            }
            return question;
        }
        else
        {
            Serial.printf("[HTTP] GET... failed, error: %s\n", http_client.errorToString(httpCode).c_str());
            speech("语音识别在线故障，请检查api是否失效");
            return "error";
        }
    }
}
// 舵机交互
void smoothMoveServo(int start, int end, int returnTo)
{
    const float pi = 3.1415926;
    int step = (start < end) ? 1 : -1;

    // 从start移动到end
    for (int i = start; i != end; i += step)
    {
        servo1.write(i);
        int delayTime = 40 * (sin((i * pi / 360.0) - pi / 2) + 1);
        delay(delayTime);
    }

    // 如果returnTo不等于-1，则返回到returnTo
    if (returnTo != -1)
    {
        step = (end < returnTo) ? 1 : -1;
        for (int i = end; i != returnTo; i += step)
        {
            servo1.write(i);
            int delayTime = 40 * (sin((i * pi / 360.0) - pi / 2) + 1);
            delay(delayTime);
        }
    }
}

#endif
